package com.free.mini.gateway.function;

import java.util.HashMap;
import java.util.Map;

import org.reactivestreams.Publisher;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.factory.rewrite.RewriteFunction;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.free.mini.common.base.ResultData;
import com.free.mini.common.utils.BizTraceUtil;
import com.free.mini.gateway.constants.GatewayConstant;
import com.free.mini.gateway.filter.GatewayContext;
import com.free.mini.gateway.utils.SignUtil;

import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono;

/**
 * response加密
 * @author dongsufeng
 * @date 2021/11/9 10:50
 * @version 1.0
 */
@Component
@Slf4j
public class EncryptFunction implements RewriteFunction<ResultData,String> {

	@Value("${gateway.key.private}")
	private String privateKey;

	@Value("${gateway.aes.decrypt.iv}")
	private String iv;

	@Override
	public Publisher<String> apply(ServerWebExchange exchange, ResultData resultData) {
		if (ObjectUtil.isEmpty(resultData)){
			return Mono.just(new JSONObject().toString());
		}
		if (log.isDebugEnabled()){
			log.debug("response encrypt resultData={}",resultData.toJSON());
		}
		try {
//			Map mock = new HashMap(1) ;
//			mock.put("test","123");
//			resultData.setData(mock);
			if (!ResultData.isSuccess(resultData)){
				return Mono.just(JSON.toJSONString(resultData));
			}
			GatewayContext gatewayContext = (GatewayContext) exchange.getAttributes().get(GatewayConstant.CACHE_GATEWAY_CONTEXT);
			if (exchange.getRequest().getMethodValue().equals(HttpMethod.GET.name())){
				return Mono.just(JSON.toJSONString(resultData));
			}
			log.info("content-type:{}",gatewayContext.getContentType().getType());
			if (!gatewayContext.getContentType().getType().equals(MediaType.APPLICATION_JSON_VALUE)){
				return Mono.just(JSON.toJSONString(resultData));
			}
			resultData.setSign(SignUtil.sign(JSON.toJSONString(resultData.getData(),SerializerFeature.MapSortField)));
			String key = SignUtil.generateAESKey();
			resultData.setRandomKey(SignUtil.rsaPrivateKeyEncrypt(privateKey, key));
			resultData.setData(SignUtil.aesEncrypt(iv,key,JSON.toJSONString(resultData.getData(),SerializerFeature.MapSortField)));
			resultData.setTraceId(BizTraceUtil.currentTraceId());
			return Mono.just(JSON.toJSONString(resultData));
		} catch (Exception e) {
			log.error("response encrypt 异常",e);
			return Mono.error(e);
		}
	}

	public static void main(String[] args) throws Exception {
		String privateKey1 = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANe2bmG2t11hweL4rd48JsBdeyZfRy8phAUqhs8sBi8lHFn8L3+VDkZH35BRPZPzDJ30a2lehBZjL+FXZCWIub16baGQgFjT2Jiod3xCa0uIvFDrpS28NAMb+gcw1VAVFJL1FVHtNKk2GYLQjZUR+oX884mKbtG4e49P9lMH7Z1vAgMBAAECgYALJEAVSfO0ngz+pSuN0/uIagunUrqBhBpujeDCqJp1KuyI9U6av18qYCH6+Uc98grPycUWfyxBX8QkVng0vBgjyfzeboPUbh0MFx5DA5lJ2yMv+oPLXIEjTcA4sVUxoRXLrSSETTGIuigFuNctc4vBx755hxGn1VnBhuEYsvu6MQJBAO51Br/xw3m5trlJN0ko4P7nlziFWhB0wopCGv6tLeQYvkcw98jz+EplARNcTP/0aQrggHM5UPP7cW7j6kp+AQkCQQDnlQwAG2gOJ30cJxMlQH23NE9ju3poUzHUiJ8qOXSHZOVScYP8VWtKfFMWSiQXriIgQ34LsyDLo/k6MJ3TG+C3AkBGfwR61I+0uenCR1n34AT8dx0m0Y251br5wudWKX6qs4H1bA2lNDNQUyIJRj1hYjF3zL1M00ISj2COpwTJ9wx5AkB9Q1CnaiuhpFh29ufTOYwGocPjhVATyBRnCrNVSpiud7PXIVGsFqQfORpULyxQpr8MxpUSTQULQZmYkR19SFIHAkEA4WW+WwuP7PGbwAyjrlcJo6e24zQ0N189zCfqULWnKGTYBm5LhMyJGEmVzjsPb148PD4Z7yGdhrWQtPlfWbCfTQ==";
		String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXtm5htrddYcHi+K3ePCbAXXsmX0cvKYQFKobPLAYvJRxZ/C9/lQ5GR9+QUT2T8wyd9GtpXoQWYy/hV2QliLm9em2hkIBY09iYqHd8QmtLiLxQ66UtvDQDG/oHMNVQFRSS9RVR7TSpNhmC0I2VEfqF/POJim7RuHuPT/ZTB+2dbwIDAQAB";
		String iv = "Ch7juDLTLwZgQNvqUpC20w==";
		String key = SignUtil.generateAESKey();
		System.out.println("key="+key);
		String randomKey = SignUtil.rsaPrivateKeyEncrypt(privateKey1, key);
		System.out.println("randomKey="+randomKey);
		Map mock = new HashMap(1) ;
		mock.put("test","123");
		String data = SignUtil.aesEncrypt(iv,key,JSON.toJSONString(mock,SerializerFeature.MapSortField));
		System.out.println(data);
		System.out.println("===========公钥解密===============");
		String decrypt_key = SignUtil.rsaPublicKeyDecrypt(publicKey, randomKey);
		System.out.println("decrypt_key="+(decrypt_key.equals(key))+"===="+decrypt_key);
		String decrypt_resp = SignUtil.aesDecrypt(iv, decrypt_key, data);
		System.out.println("decrypt_resp="+decrypt_resp);
		System.out.println("============公钥加密========");
		String pu_key = SignUtil.generateAESKey();
		String pu_randomKey = SignUtil.rsaPublicKeyEncrypt(publicKey, pu_key);
		String pu_data = SignUtil.aesEncrypt(iv, pu_key, JSON.toJSONString(mock));
		String keyDecrypt = SignUtil.rsaPrivateKeyDecrypt(privateKey1, pu_randomKey);
		System.out.println("keyDecrypt="+keyDecrypt);
		String resp = SignUtil.aesDecrypt(iv, keyDecrypt, pu_data);
		System.out.println("resp="+resp);
	}
}
